 'use strict';

const BaseService = require('../../libs/base/BaseService');
const fs = require('fs');
const path = require('path');
const moment = require('moment');

/**
 * 日志级别
 */
const LogLevel = {
  DEBUG: 'debug',
  INFO: 'info',
  WARN: 'warn',
  ERROR: 'error'
};

/**
 * Logger服务，负责日志记录
 */
class Logger extends BaseService {
  /**
   * 构造函数
   */
  constructor() {
    super('Logger');
    
    this._logDir = path.resolve(process.cwd(), 'log');
    this._currentDate = moment().format('YYYY-MM-DD');
    this._logStream = null;
    this.date = this._currentDate;
    
    this._logLevel = this.isDebug ? LogLevel.DEBUG : LogLevel.INFO;
    
    console.log(`[Logger] 构造函数 isDebug=${this.isDebug}, logLevel=${this._logLevel}`);
  }
  
  /**
   * 初始化服务
   */
  async init() {
    // 确保日志目录存在
    await this._ensureLogDir();
    
    // 创建日志流
    this._createLogStream();
    
    console.log(`[Logger] 服务初始化完成，日志级别: ${this._logLevel}, 调试模式: ${this.isDebug ? '开启' : '关闭'}`);
  }

  /**
   * 确保日志目录存在
   * @private
   */
  async _ensureLogDir() {
    if (!fs.existsSync(this._logDir)) {
      fs.mkdirSync(this._logDir, { recursive: true });
    }
  }

  /**
   * 创建日志流
   * @private
   */
  _createLogStream() {
    const date = moment().format('YYYY-MM-DD');
    const logFile = path.join(this._logDir, `${date}.log`);
    
    // 如果日期变了，关闭旧的流并创建新的
    if (date !== this._currentDate) {
      this._closeLogStream();
      this._currentDate = date;
      this.date = date;
    }
    
    // 创建新的流
    if (!this._logStream) {
      this._logStream = fs.createWriteStream(logFile, { flags: 'a' });
    }
  }

  /**
   * 关闭日志流
   * @private
   */
  _closeLogStream() {
    if (this._logStream) {
      this._logStream.end();
      this._logStream = null;
    }
  }
  /**
   * 写入日志
   * @param {string} level 日志级别
   * @param {Array} args 参数数组，前两个参数为服务名和端口号
   * @private
   */
  async _writeLog(level, ...args) {
    // 确保流存在
    this._createLogStream();
    
    // 从参数数组中获取服务名和端口号
    const serviceName = args[0] || 'Unknown';
    const servicePort = args[1] || '0';
    const message = args.slice(2).join(' ');
    
    // 格式化日志消息
    const timestamp = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
    const logMessage = `[${timestamp}] [${serviceName}-${servicePort}] [${level.toUpperCase()}] ${message}\n`;
    
    // 写入日志
    this._logStream.write(logMessage);
    
    // 同时输出到控制台
    console.log(logMessage.trim());
    
    return true;
  }

  /**
   * 记录普通日志
   * @param {Array} args 参数数组，前两个参数为服务名和端口号
   * @returns {Promise<boolean>} 是否成功
   */
  async log(...args) {
    return this.info(...args);
  }

  /**
   * 记录信息日志
   * @param {Array} args 参数数组，前两个参数为服务名和端口号
   * @returns {Promise<boolean>} 是否成功
   */
  async info(...args) {
    if (this._isLevelEnabled(LogLevel.INFO)) {
      return this._writeLog(LogLevel.INFO, ...args);
    }
    return false;
  }

  /**
   * 记录警告日志
   * @param {Array} args 参数数组，前两个参数为服务名和端口号
   * @returns {Promise<boolean>} 是否成功
   */
  async warn(...args) {
    if (this._isLevelEnabled(LogLevel.WARN)) {
      return this._writeLog(LogLevel.WARN, ...args);
    }
    return false;
  }

  /**
   * 记录错误日志
   * @param {Array} args 参数数组，前两个参数为服务名和端口号
   * @returns {Promise<boolean>} 是否成功
   */
  async error(...args) {
    if (this._isLevelEnabled(LogLevel.ERROR)) {
      return this._writeLog(LogLevel.ERROR, ...args);
    }
    return false;
  }

  /**
   * 记录调试日志
   * @param {Array} args 参数数组，前两个参数为服务名和端口号
   * @returns {Promise<boolean>} 是否成功
   */
  async debug(...args) {
    // 如果不是调试模式，不记录调试日志
    if (!this.isDebug) {
      return false;
    }
    
    if (this._isLevelEnabled(LogLevel.DEBUG)) {
      // 调试日志只输出到控制台，不写入日志文件
      const timestamp = moment().format('YYYY-MM-DD HH:mm:ss');
      const serviceName = args[0] || 'Unknown';
      const servicePort = args[1] || '0';
      const message = args.slice(2).join(' ');
      const logMessage = `[${timestamp}] [${serviceName}-${servicePort}] [DEBUG] ${message}`;
      console.log(logMessage);
      return true;
    }
    return false;
  }

  /**
   * 设置日志级别
   * @param {string} level 日志级别
   * @returns {boolean} 是否成功
   */
  setLogLevel(level) {
    if (Object.values(LogLevel).includes(level)) {
      this._logLevel = level;
      return true;
    }
    return false;
  }

  /**
   * 检查日志级别是否启用
   * @param {string} level 日志级别
   * @returns {boolean} 是否启用
   * @private
   */
  _isLevelEnabled(level) {
    const levels = Object.values(LogLevel);
    const currentIndex = levels.indexOf(this._logLevel);
    const targetIndex = levels.indexOf(level);
    
    return targetIndex >= currentIndex;
  }

  /**
   * 停止服务
   */
  async stop() {
    this._closeLogStream();
    console.log('[Logger] 服务已停止');
  }
}

module.exports = Logger; 